/*
 * Copyright (C) 2014 luke.
 * 
 * This file is part of Silvie.
 * 
 * Silvie is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Silvie is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Silvie.  If not, see <http://www.gnu.org/licenses/>.
 */

package silvie.gui;

import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Toolkit;
import java.util.HashMap;
import java.util.Map;
import java.util.prefs.Preferences;

import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;

import silvie.Silvie;

/**
 * Helper class to create and manage the GUI components.
 * 
 * @author luke
 */
public class SilvieGUI {
	public static final String SILVER_ICON_PATH = "silvie/gui/bitmaps/silver.png";
	public static final String FILE_ICON_PATH = "silvie/gui/bitmaps/file.png";
	public static final String SUPPORTED_ICON_PATH = "silvie/gui/bitmaps/supported.png";
	public static final String DIRECTORY_ICON_PATH = "silvie/gui/bitmaps/directory.png";
	public static final String EXPANDED_ICON_PATH = "silvie/gui/bitmaps/expanded.png";
	private static final int FRAME_SPACING = 10;
	public static final String OPEN_DIALOG_MESSAGE = "Open the Silver data directory";
	public static final String SAVE_DIALOG_MESSAGE = "Save the selected resource";
	private static final Map<String, ImageIcon> ICON_CACHE = new HashMap<String, ImageIcon>();
	private FileExplorer fileExplorer;
	private Preview preview;

	/**
	 * SilvieGUI constructor. It launches the creation of the preview and file
	 * explorer frames, and centers them on the screen.
	 * 
	 * @param silvie the controller.
	 */
	public SilvieGUI(Silvie silvie) {
		this.preview = new Preview();
		this.fileExplorer = new FileExplorer(silvie);
		JFrame explorerFrame = this.fileExplorer.getFrame();
		Frame previewFrame = this.preview.getFrame();
		Dimension desktopDimension = Toolkit.getDefaultToolkit().getScreenSize();
		Dimension explorerDimension = explorerFrame.getSize();
		Dimension previewDimension = previewFrame.getSize();
		int availableWidth = desktopDimension.width - previewDimension.width - explorerDimension.width;
		explorerFrame.setLocation(((availableWidth - FRAME_SPACING) / 2), (desktopDimension.height - explorerDimension.height) / 2);
		previewFrame.setLocation(((availableWidth + FRAME_SPACING) / 2) + explorerDimension.width, (desktopDimension.height - previewDimension.height) / 2);
	}

	/**
	 * Opens a JFileChooser dialog for choosing the Silver data directory.
	 * 
	 * @param preferences the Silvie Preferences.
	 * @param initialPath the directory initially pointed to.
	 * @return true if the user validates the dialog, false otherwise.
	 */
	public boolean openDataDirectory(Preferences preferences, String initialPath) {
		JFileChooser chooser = new JFileChooser(initialPath);
		chooser.setDialogTitle(OPEN_DIALOG_MESSAGE);
		chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		boolean approved = chooser.showOpenDialog(this.preview.getFrame()) == JFileChooser.APPROVE_OPTION;
		if (approved) {
			preferences.put(Silvie.DATA_PATH_PREFERENCES_KEY, chooser.getSelectedFile().getAbsolutePath());
		}
		return approved;
	}

	/**
	 * Retrieves an icon by path. If the icon is not cached yet, this method
	 * will load it and cache it first.
	 * 
	 * @param iconPath the icon path.
	 * @return an ImageIcon for the icon.
	 */
	public static ImageIcon getCachedIcon(String iconPath) {
		ImageIcon icon = ICON_CACHE.get(iconPath);
		if (icon != null) {
			return icon;
		} else {
			icon = new ImageIcon(SilvieGUI.class.getClassLoader().getResource(iconPath));
			ICON_CACHE.put(iconPath, icon);
			return icon;
		}
	}

	/**
	 * Sets the visibility of the file explorer and preview frames.
	 * 
	 * @param visible true for visible, false otherwise.
	 */
	public void setFramesVisible(boolean visible) {
		this.fileExplorer.getFrame().setVisible(visible);
		this.preview.getFrame().setVisible(visible);
	}

	public FileExplorer getFileExplorer() {
		return this.fileExplorer;
	}

	public Preview getPreview() {
		return this.preview;
	}
}
